package academic.emailClient.model.entities;

import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.HashMap;

import academic.emailClient.persistence.TemplateFileDAO;
import academic.emailClient.security.model.User;
import academic.emailClient.utils.TemplateFormatter;


public class MeetingMessageTemplate {
	private static String path = "." + File.separator + "Own Templates";
	private static String ACCEPT_MEETING = "accept_meeting";
	private static String ACCEPTED = "ACCEPTED";
	private static String DECLINED_MEETING = "decline_meeting";
	private static String DECLINED = "DECLINED";
	private static String NEW_MEETING = "new_meeting";
	private static String NEW = "NEW";
	private static String UPDATED_MEETING = "update_meeting";
	private static String UPDATED = "UPDATED";
	private static String CANCEL_MEETING = "delete_meeting";
	private static String CANCELLED = "CANCELLED";
	
	/**
	 * Creates a message with the meeting acceptance notification
	 * @param meeting
	 * @return
	 */
	public static Message createAcceptanceConfirmationMessage(Meeting meeting, User user){
		return createConfirmationMessage(meeting, ACCEPT_MEETING, ACCEPTED, user);
	}
	
	/**
	 * Creates a message with the meeting cancellation notification
	 * @param meeting
	 * @return
	 */
	public static Message createCancellationConfirmationMessage(Meeting meeting, User user){
		return createConfirmationMessage(meeting, DECLINED_MEETING, DECLINED, user);
	}
	
	/**
	 * Creates a message that is going to notify the creation of a new meeting
	 * @param meeting 
	 * @return Notification message
	 */
	public static Message createNewMeetingNotification(Meeting meeting){
		return createNotificationMessage(meeting, NEW_MEETING, NEW);
	}
	
	/**
	 * Creates a message that is going to notify the modification of a  meeting
	 * @param meeting 
	 * @return Notification message
	 */
	public static Message createUpdatedMeetingNotification(Meeting meeting){
		return createNotificationMessage(meeting, UPDATED_MEETING, UPDATED);
	}
	
	
	/**
	 * Creates a message that is going to notify the cancellation of a  meeting
	 * @param meeting 
	 * @return Notification message
	 */
	public static Message createCancellationMeetingNotification(Meeting meeting){
		return createNotificationMessage(meeting, CANCEL_MEETING, CANCELLED);
	}
	
	/**
	 * Creates a new message with a meeting notification
	 * @param meeting Meeting that is going to be notified
	 * @param templateName Name of the template that contains message text
	 * @param notificationType Type of notification that is going to be given
	 * @return
	 */
	private static Message createNotificationMessage(Meeting meeting, String templateName, String notificationType){
		MessageBuilder message = new MessageBuilder();
		
		HashMap<String, String> variables = createVariableMap(meeting);
		String bodyMessage = buildBodyMessage(meeting, templateName, variables);
		String subject = buildSubject(meeting, notificationType);
		String attendeesAccounts = buildReceiversString(meeting);
		
		Message newMessage = message.withFrom(meeting.getOwner())
									.withSubject(subject)
									.withBodyMessage(bodyMessage)
									.withTo(attendeesAccounts)
									.build();
		return newMessage;
	}

	/**
	 * Creates a new message with a meeting notification
	 * @param meeting Meeting that is going to be notified
	 * @param templateName Name of the template that contains message text
	 * @param notificationType Type of notification that is going to be given
	 * @param user User 
	 * @return
	 */
	private static Message createConfirmationMessage(Meeting meeting, String templateName, String notificationType, User user){
		MessageBuilder message = new MessageBuilder();
		HashMap<String, String> variables = createVariableMap(meeting);
		variables.put(MeetingAttributes.ATTENDEE.name(), user.getFullname());
		
		String bodyMessage = buildBodyMessage(meeting, templateName, variables);
		String subject = buildSubject(meeting, notificationType);
		
		Message newMessage = message.withFrom(user.getEmail())
									.withSubject(subject)
									.withBodyMessage(bodyMessage)
									.withTo(meeting.getOwner())
									.build();
		return newMessage;
	}

	
	/**
	 * Creates a map with the variables that must be replaced in the template
	 * @param meeting Meeting that has the attributes
	 * @return
	 */
	private static HashMap<String, String> createVariableMap(Meeting meeting){
		DateFormat date = new SimpleDateFormat("MMM dd, hh:mm:ss aaa");
		HashMap<String, String> variables = new HashMap<String, String>();
		
		//Adding meeting variables
		variables.put(MeetingAttributes.ID.name(), meeting.getId().toString());
		variables.put(MeetingAttributes.PURPOSE.name(), meeting.getPurpose());
		variables.put(MeetingAttributes.DESCRIPTION.name(), meeting.getDescription());
		variables.put(MeetingAttributes.LOCATION.name(), meeting.getLocation());
		variables.put(MeetingAttributes.START.name(), date.format(meeting.getStart()));
		variables.put(MeetingAttributes.END.name(), date.format(meeting.getEnd()));
		return variables;
	}
	
	/**
	 * Builds the body of the message with a template and using the meeting information
	 * @param meeting Meeting
	 * @param templateName Name of the template file
	 * @param variables Variables that are going to be replaced in text
	 * @return Body of the message
	 */
	private static String buildBodyMessage(Meeting meeting, String templateName, HashMap<String, String> variables){
		String template = TemplateFileDAO.read(path, templateName);
		template = TemplateFormatter.format(template, variables);
		return template;
	}
	
	/**
	 * Builds the string of the receivers accounts
	 * @param meeting Meeting with the attendees
	 * @return List of email accounts separated by semi colon ;
	 */
	private static String buildReceiversString(Meeting meeting){
		String attendeesAccounts = "";
		for (String attendeeAccount : meeting.getAttendeesEmails()){
			attendeesAccounts += (attendeesAccounts.equals("") ? "" : ";") + attendeeAccount; 
		}
		return attendeesAccounts;
	}
	
	/**
	 * Builds the subject of the notification
	 * @param meeting
	 * @param notificationType 
	 * @return Subject with meeting information
	 */
	private static String buildSubject(Meeting meeting, String notificationType){
		String subjectTemplate = "${TYPE} Meeting: ${PURPOSE} - <${ID}>";
		HashMap<String, String> variables = createVariableMap(meeting);
		variables.put("TYPE", notificationType);
		return TemplateFormatter.format(subjectTemplate, variables);
	}

}
